package com.xidata.dict.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xidata.dict.entity.CodeDict;
import com.xidata.dict.mapper.CodeDictMapper;
import com.xidata.dict.service.CodeDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class CodeDictServiceImpl implements CodeDictService {

    @Resource
    CodeDictMapper codeDictMapper;

    @Override
    public Optional<CodeDict> lookup(String codeType, String code, String language) {
        LambdaQueryWrapper<CodeDict> queryWrapper = getQueryWrapper(codeType, code, language);
        CodeDict codeDict = codeDictMapper.selectOne(queryWrapper);
        return Optional.ofNullable(codeDict);
    }

    @Override
    public List<CodeDict> findByCodeType(String codeType) {
        LambdaQueryWrapper<CodeDict> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CodeDict::getCodeType, codeType);
        return codeDictMapper.selectList(queryWrapper);
    }

    @Override
    public Optional<CodeDict> lookupSameTranslate(String sourceLanguage, String sourceText, String targetLanguage) {
        LambdaQueryWrapper<CodeDict> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CodeDict::getLanguage, sourceLanguage).eq(CodeDict::getCode, sourceText);

        List<CodeDict> sameSource = codeDictMapper.selectList(queryWrapper);
        if (sameSource.isEmpty()) return Optional.empty();

        for (CodeDict codeDict : sameSource) {
            LambdaQueryWrapper<CodeDict> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CodeDict::getLanguage, targetLanguage)
                    .eq(CodeDict::getCodeType, codeDict.getCodeType())
                    .eq(CodeDict::getCode, codeDict.getCode());
            List<CodeDict> sameTarget = codeDictMapper.selectList(wrapper);
            if (!sameTarget.isEmpty()) {
                return Optional.ofNullable(sameTarget.get(0));
            }
        }
        return Optional.empty();
    }

    @Override
    public void add(String codeType, String code, String language, String text) {
        Optional<CodeDict> lookup = lookup(codeType, code, language);
        if (!lookup.isPresent()) {
            CodeDict other = new CodeDict(codeType, code, language, text);
            codeDictMapper.insert(other);
        } else {
            CodeDict codeDict = lookup.get();
            codeDict.setText(text);
            codeDictMapper.updateById(codeDict);
        }
    }

    @Override
    public void add(CodeDict codeDict) {
        add(codeDict.getCodeType(), codeDict.getCode(), codeDict.getLanguage(), codeDict.getText());
    }

    @Override
    public void batchAdd(Collection<CodeDict> collection) {
        collection.forEach(this::add);
    }

    @Override
    public void removeAll() {
        LambdaQueryWrapper<CodeDict> queryWrapper = getQueryWrapper(null, null, null);
        codeDictMapper.delete(queryWrapper);
    }

    @Override
    public void remove(String codeType) {
        LambdaQueryWrapper<CodeDict> queryWrapper = getQueryWrapper(codeType, null, null);
        codeDictMapper.delete(queryWrapper);
    }

    @Override
    public void remove(String codeType, String code) {
        LambdaQueryWrapper<CodeDict> queryWrapper = getQueryWrapper(codeType, code, null);
        codeDictMapper.delete(queryWrapper);
    }

    @Override
    public void remove(String codeType, String code, String language) {
        LambdaQueryWrapper<CodeDict> queryWrapper = getQueryWrapper(codeType, code, language);
        codeDictMapper.delete(queryWrapper);
    }

    private LambdaQueryWrapper<CodeDict> getQueryWrapper(String codeType, String code, String language) {

        LambdaQueryWrapper<CodeDict> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(codeType)) queryWrapper.eq(CodeDict::getCodeType, codeType);
        if (StringUtils.isNotEmpty(code)) queryWrapper.eq(CodeDict::getCode, code);
        if (StringUtils.isNotEmpty(language)) queryWrapper.eq(CodeDict::getLanguage, language);

        return queryWrapper;

    }
}
